package com.example._06springaop.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/*
  @Aspect表示当前类是切面类
 */
@Component
@Aspect
public class LogAspect {
    //切入点
    @Pointcut("execution(* com.example._06springaop.aop.CalculatorImp.*(..))")
    public void dotime() {
    }

//    //前置注解释，调用目标方法前执行
//    @Before("execution(public int com.example._06springaop.aop.CalculatorImp.*(..))")
//    public void beforeMethod(JoinPoint joinPoint) {
//        String methodName = joinPoint.getSignature().getName();
//        String args = Arrays.toString(joinPoint.getArgs());
//        System.out.println("xxx方法开始");
//    }
//    //后置通知，目标方法结束（包含正常和异常的结束）
//    @After("execution(public int com.example._06springaop.aop.CalculatorImp.*(..))")
//    public void afterMethod(JoinPoint joinPoint){
//        String name = joinPoint.getSignature().getName();
//        System.out.println(name+"方法结束");
//    }
//    //目标方法的正常执行后执行，可以获取到目标方法的返回值
//    @AfterReturning(value = "dotime()",returning = "result")
//    public void afterMtehod(JoinPoint joinPoint,Object result){
//        String name = joinPoint.getSignature().getName();
//        System.out.println(name+"方法正常返回，返回结果是"+result);
//        System.out.println(name+"方法正常返回，返回通知是"+joinPoint.getSignature().getName());
//    }
    //@AfterThrowing异常通知，目标方法出现异常后执行,可以获取到目标方法的异常信息；如果正常则不执行
    @AfterThrowing(value = "dotime()",throwing = "exception")
        public void afterThrowing(JoinPoint joinPoint,Exception exception){
        String name = joinPoint.getSignature().getName();
        System.out.println(name+"方法出现异常，异常信息是"+exception);
    }
    /*
        环绕通知，环绕通知是目标方法执行前后分别执行，
        可以获取到目标方法的返回值和异常信息
     */
    @Around("dotime()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        Object result = null;
        try {
            System.out.println("环绕通知前置");
            result = joinPoint.proceed();
            System.out.println("环绕返回通知");
        }catch(Throwable e){
            System.out.println("环绕通知异常");
            throw new RuntimeException(e);

        }finally{
            System.out.println("环绕通知后置");
        }
        /*
        try(){前置通知；返回通知；执行目标方法；}
        catch(){异常通知；}
        finally(){后置通知；}
         */
        return result;

    }
}
